package com.fundamental.lock;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class LockTest {


    static ReentrantLock lock1 = new ReentrantLock();

    static ReentrantLock lock2 = new ReentrantLock();

    static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    static SimpleExclusiveSync sync = new SimpleExclusiveSync();


    public static void main(String[] args) {
        //java 没有自带的死锁检测功能，但是有锁资源释放时的检测。
        //new LockThread().start();
        //new ReverseLockThread().start();

        /*Condition tmp;
        (tmp = lock1.newCondition()).await();

        tmp.signal();*/

        //unsafe必须systemclassloader加载的类才能获得，所以在调用他之前，先用System的classLoader加载一下。但是ClassLoader.getSystemClassLoader时获得的好像并不是系统loader，仍然是应用loader。

        //遗留1：取SystemClassLoader的过程是什么，为什么取出来一个应用loader
        //遗留2：怎么样使用unsafe。

        //针对遗留2，那就是使用反射拿到unsafe


       ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
        try {
            //getResource使用路径名
            //systemLoader.getResource();
            //loadClass使用包名
            systemLoader.loadClass("com.fundamental.lock.SimpleExclusiveSync");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


        long before = System.currentTimeMillis();

        int threadCount = 200;
        CountDownLatch latch = new CountDownLatch(threadCount);
        for (int i = 1; i <= threadCount; i++) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        int count = 10000;
                        int range = 10000;
                        List<Integer> list = generateRandomCollection(count, range);
                        //sync.attempt(1000l);
                        //sync.acquire();
                        lock1.lock();
                       // readWriteLock.readLock().lock();
                        System.out.println(Thread.currentThread().getName()+"获得了锁");
                        Collections.sort(list);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println(Thread.currentThread().getName()+"准备释放锁");
                        lock1.unlock();
                        //sync.release();
                        //readWriteLock.readLock().unlock();
                    }
                    latch.countDown();
                    System.out.println(Thread.currentThread().getName()+"完成"+latch.getCount());
                }

                private List<Integer> generateRandomCollection(int count, int range) {
                    List<Integer> list = new ArrayList<>();
                    Random random = ThreadLocalRandom.current();
                    for (int i = 1; i <= count; i++) {
                        list.add(random.nextInt(range));
                    }
                    return list;
                }
            }.start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long after = System.currentTimeMillis();

        System.out.println(after - before);
    }




    public static class LockThread extends Thread{

        int count;

        @Override
        public void run() {
            while (true) {
                //lock1.lock();
                //lock2.lock();
                synchronized (lock1) {
                    synchronized (lock2) {
                        System.out.println(Thread.currentThread().getName() + count++);
                    }
                }
                //lock2.unlock();
                //lock1.unlock();
            }
        }
    }

    public static class ReverseLockThread extends Thread{

        int count;

        @Override
        public void run() {
            while(true) {
                //lock2.lock();
                //lock1.lock();
                synchronized (lock2) {
                    synchronized (lock1) {
                        System.out.println(Thread.currentThread().getName() + count++);
                    }
                }
                //lock1.unlock();
                //lock2.unlock();
            }
        }
    }





}



